package com.ev.scm.service.impl;

import com.ev.apis.model.DsResultResponse;
import com.ev.common.enums.AuditStatusDict;
import com.ev.framework.config.Constant;
import com.ev.framework.config.ConstantForGYL;
import com.ev.framework.il8n.MessageSourceHandler;
import com.ev.framework.utils.DateFormatUtil;
import com.ev.framework.utils.R;
import com.ev.framework.utils.ShiroUtils;
import com.ev.framework.utils.StringUtils;
import com.ev.scm.dao.CostAdjustmentDao;
import com.ev.scm.dao.CostAdjustmentItemDao;
import com.ev.scm.domain.CostAdjustmentDO;
import com.ev.scm.domain.CostAdjustmentItemDO;
import com.ev.scm.service.CostAdjustmentService;
import com.ev.scm.service.StockService;
import com.ev.scm.vo.CostAdjustmentPageParam;
import com.ev.scm.vo.CostAdjustmentSaveParam;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;


@Service
public class CostAdjustmentServiceImpl implements CostAdjustmentService {
    @Autowired
    private CostAdjustmentDao costAdjustmentDao;
    @Autowired
    private CostAdjustmentItemDao costAdjustmentItemDao;
    @Autowired
    private MessageSourceHandler messageSourceHandler;
    @Autowired
    private StockService stockService;


    @Override
    public CostAdjustmentDO get(Long id) {
        return costAdjustmentDao.get(id);
    }

    @Override
    public List<CostAdjustmentDO> list(Map<String, Object> map) {
        return costAdjustmentDao.list(map);
    }

    @Override
    public int count(Map<String, Object> map) {
        return costAdjustmentDao.count(map);
    }

    @Override
    public int save(CostAdjustmentDO costAdjustment) {
        return costAdjustmentDao.save(costAdjustment);
    }

    @Override
    public int update(CostAdjustmentDO costAdjustment) {
        return costAdjustmentDao.update(costAdjustment);
    }

    @Override
    public int updateAll(CostAdjustmentDO costAdjustment) {
        return costAdjustmentDao.updateAll(costAdjustment);
    }

    @Override
    public int remove(Long id) {
        return costAdjustmentDao.remove(id);
    }

    @Override
    public int batchRemove(Long[] ids) {
        return costAdjustmentDao.batchRemove(ids);
    }

    @Override
    public R saveAndVerify(CostAdjustmentSaveParam saveParam) {
        List<CostAdjustmentItemDO> costAdjustmentItemDOList = saveParam.getCostAdjustmentItemDO();
        if (costAdjustmentItemDOList == null || costAdjustmentItemDOList.size() == 0) {
            return R.error();
        }

        CostAdjustmentDO costAdjustmentDO = saveParam.getCostAdjustmentDO();
        Long id = costAdjustmentDO.getId();
        boolean isUpdate = id != null;
        Map<String, Object> result = Maps.newHashMap();
        if (isUpdate) {
            // 修改主表
            costAdjustmentDao.update(costAdjustmentDO);

            // 操作子表
            // 删除明细行
            List<Long> itemIds = saveParam.getItemIds();
            if (itemIds != null && itemIds.size() > 0) {
                costAdjustmentItemDao.batchRemove(itemIds.toArray(new Long[0]));
            }
            List<CostAdjustmentItemDO> updateItemList = costAdjustmentItemDOList.stream().filter(e -> e.getId() != null).collect(Collectors.toList());
            if (updateItemList.size() > 0) {
                costAdjustmentItemDao.batchUpdate(updateItemList);
            }
            costAdjustmentItemDOList.removeAll(updateItemList);

            if (costAdjustmentItemDOList.size() > 0) {
                long headId = id;
                costAdjustmentItemDOList.forEach(e -> e.setHeadId(headId));
                costAdjustmentItemDao.batchSave(costAdjustmentItemDOList);
            }
            result.put("id", id);
            return R.ok(result);
        }

        // 保存
        costAdjustmentDO.setAuditSign(AuditStatusDict.WAIT_AUDIT.getId());
        costAdjustmentDO.setCode(this.getCode());
        costAdjustmentDao.save(costAdjustmentDO);
        id = costAdjustmentDO.getId();
        long headId = id;
        costAdjustmentItemDOList.forEach(e -> e.setHeadId(headId));
        costAdjustmentItemDao.batchSave(costAdjustmentItemDOList);
        result.put("id", id);
        return R.ok(result);
    }

    private synchronized String getCode() {
        Map<String, Object> param = Maps.newHashMapWithExpectedSize(3);
        param.put("offset", 0);
        param.put("limit", 1);
        List<CostAdjustmentDO> list = this.list(param);
        return DateFormatUtil.getWorkOrderNo(ConstantForGYL.COST_ADJUST_PREFIX, list.size() > 0 ? list.get(0).getCode() : null, 4);
    }

    @Override
    public Map<String, Object> getById(Long id) {
        Map<String, Object> costAdjustment = costAdjustmentDao.getById(id);
        Map<String, Object> result = Maps.newHashMap();
        if (costAdjustment != null) {
            List<Map<String, Object>> bodyDetail = costAdjustmentItemDao.getByHeadId(id);
            result.put("headDetail", costAdjustment);
            result.put("bodyDetail", bodyDetail);
            return result;
        }
        return result;
    }

    @Override
    public Map<String, Object> pageList(CostAdjustmentPageParam pageParam) {
        Map<String, Object> result = Maps.newHashMap();
        pageParam.setMaterielName(StringUtils.sqlLike(pageParam.getMaterielName()));

        List<Map<String, Object>> data = costAdjustmentDao.pageList(pageParam);
        if (data.size() > 0) {
            Map<String, Object> pageCount = costAdjustmentDao.pageCount(pageParam);
            int total = Integer.parseInt(pageCount.get("total").toString());
            result.put("data", new DsResultResponse(pageParam.getPageno(), pageParam.getPagesize(), total, data));
            result.put("total", pageCount);
        }
        return result;
    }

    @Override
    public R reverseAudit(Long id) {
        CostAdjustmentDO costAdjustmentDO = this.get(id);

        if (Objects.equals(costAdjustmentDO.getAuditSign(), AuditStatusDict.WAIT_AUDIT.getId())) {
            return R.error(messageSourceHandler.getMessage("receipt.reverseAudit.nonWaitingAudit", null));
        }
        // 获取本次期间
        Date periodTime = stockService.getPeriodTime();
        boolean isPeriodEnd = periodTime.after(costAdjustmentDO.getChooseTime());
        if (isPeriodEnd) {
            return R.error(messageSourceHandler.getMessage("scm.operate.isCarryOver", null));
        }

        costAdjustmentDO.setAuditSign(AuditStatusDict.WAIT_AUDIT.getId());
        costAdjustmentDO.setAuditor(null);
        costAdjustmentDO.setAuditTime(null);
        costAdjustmentDao.updateAll(costAdjustmentDO);

        return R.ok();
    }

    @Override
    public R audit(Long id) {
        CostAdjustmentDO costAdjustmentDO = this.get(id);
        if (Objects.equals(costAdjustmentDO.getAuditSign(), AuditStatusDict.OK_AUDIT.getId())) {
            return R.error(messageSourceHandler.getMessage("common.duplicate.approved", null));
        }
        // 获取本次期间
        Date periodTime = stockService.getPeriodTime();
        boolean isPeriodEnd = periodTime.after(costAdjustmentDO.getChooseTime());
        if (isPeriodEnd) {
            return R.error(messageSourceHandler.getMessage("scm.operate.isCarryOver", null));
        }

        costAdjustmentDO.setAuditSign(AuditStatusDict.OK_AUDIT.getId());
        costAdjustmentDO.setAuditor(ShiroUtils.getUserId());
        costAdjustmentDO.setAuditTime(new Date());
        costAdjustmentDao.update(costAdjustmentDO);

        return R.ok();
    }

    @Override
    public R batchDelete(List<Long> ids) {
        Map<String, Object> param = Maps.newHashMap();
        param.put("ids", ids);
        List<CostAdjustmentDO> costAdjustmentDOList = costAdjustmentDao.list(param);
        // 检验是否有审核状态的
        boolean isOkAudit = costAdjustmentDOList.stream().anyMatch(e -> Objects.equals(e.getAuditSign(), Constant.OK_AUDITED));
        if (isOkAudit) {
            return R.error(messageSourceHandler.getMessage("common.submit.delete.disabled", null));
        }
        // 获取本次期间
        Date periodTime = stockService.getPeriodTime();
        boolean isPeriodEnd = costAdjustmentDOList.stream().anyMatch(e -> periodTime.after(e.getChooseTime()));
        if (isPeriodEnd) {
            return R.error(messageSourceHandler.getMessage("scm.operate.isCarryOver", null));
        }
        // 删除
        Long[] idsToArray = ids.toArray(new Long[0]);
        costAdjustmentDao.batchRemove(idsToArray);
        costAdjustmentItemDao.batchRemoveByHeadIds(idsToArray);

        return R.ok();
    }

}
